using System;
using System.Net.Sockets;

namespace Stunt.Nutss
{

	/// <summary>Abstracts a signaling service</summary>
	public interface ISignalingContext
	{

		#region RegisterChannel / Register

		/// <summary>Registers the socket that will receive events.</summary>
		/// <param name="selector">Selector to register with</param>
		/// <returns>Key for registration</returns>
		Socket RegisterChannel();
		/// <summary>Registers a local endpoint with the signaling service.</summary>
		/// <param name="localAddress">signaling address for the local endpoint</param>
		/// <returns>Continuation to refresh registration if needed, null otherwise</returns>
		/// <throws>UnknownHostException if registration server cannot be found</throws>
		IContinuation Register(NutssUri localAddress);

		#endregion

		#region Send / Receive

		/// <summary>Retrieves a signaling message after activity on the signaling channel.</summary>
		/// <returns>message retrieved</returns>
		/// <throws>IOException if a socket error occurs</throws>
		ISignalingMessage Receive();

		/// <summary> Sends a signaling message. </summary>
		/// <param name="msg">message to send</param>
		/// <throws>  IOException if a socket error occurs </throws>
		void Send(ISignalingMessage msg);

		#endregion

		#region Message management

		/// <summary>Creates a signaling message</summary>
		/// <param name="localAddress">source signaling address</param>
		/// <param name="remoteAddress">destination signaling address</param>
		/// <param name="payload">message payload</param>
		/// <returns> newly allocated message</returns>
		ISignalingMessage CreateMessage(NutssUri localAddress, NutssUri remoteAddress, object payload);
		/// <summary> Creates a reply to a signaling message</summary>
		/// <param name="msg">message to reply</param>
		/// <param name="payload">message payload</param>
		/// <returns>newly allocated reply message</returns>
		ISignalingMessage CreateReply(ISignalingMessage msg, object payload);
		/// <summary>Modifies a signaling message.</summary>
		/// <param name="msg">message to modify</param>
		/// <param name="payload">message payload</param>
		/// <returns> modified message </returns>
		ISignalingMessage SetMessage(ISignalingMessage msg, object payload);

		#endregion

		#region Close

		/// <summary>Closes a signaling channel.</summary>
		void Close();

		#endregion

	}
}